Od pomysłu do przemysłu
W moim ostatnim tekście opublikowanym w magazynie @t dowodziłem, że każdy nieprogramista, który potrafi zdobyć się na analityczne podejście do rozwiązania dowolnego problemu ma w gruncie rzeczy z programistami wiele wspólnego. Dzieje się tak właśnie ze względu na analityczne myślenie, które wyróżnia programistów (i nie tylko programistów). Tym razem chciałbym pokazać jak łatwo jest przejść od teorii do praktyki. Wiedza, którą czytelnik musi posiadać aby podołać temu zadaniu jest naprawdę niewielka - to co jest naprawdę ważne to wzmiankowane wyżej "analityczne myślenie".
Zacznę od przypomnienia. Programiści poruszają się w świecie algorytmów. Algorytm - sposób rozwiązywania określonego problemu w skończonej ilości kroków - jest tym czego każdy przedstawiciel tego zacnego zawodu poszukuje. Trzeba tutaj dodać, iż wymyślenie algorytmu - optymalnego z punktu widzenia stawianych wymagań - jest czynnością, która daje bardzo wiele satysfakcji. Dla sprawnego zapisywania algorytmów wymyślono graficzne symbole (bloki), które przedstawiają typowe operacje. Na rysunku 1 przedstawiono cztery bloki służace temu zadaniu.

Rysunek 1. a) Blok wykonania operacji, b) Blok warunkowy,
c) Blok wprowadzania danych, d) Blok uzyskiwania informacji
Bloki przedstawione na rysunku mają w literaturze fachowej różne nazwy (rzadko takie jak prezentowane tutaj) i dlatego zaprezentowane nazwy mogą u osób uprawiających zawód programisty budzić zastrzeżenia. W mojej opinii nazewnictwo nie jest jednak wcale istotne dla zrozumienia idei i powinno ono raczej służyć czytelnikowi niż trzymać się standardu. A idea stosowania tych bloków jest bardzo prosta. Chodzi o zamodelowanie algorytmu przy ich pomocy, tak by można było łatwo zrozumieć sam algorytm. Do wnętrza każdego bloku wpisuje się pewne informacje, które razem z jego kształtem mówią o czynności jaka zostanie podjęta gdy sterowanie dojdzie do tego bloku. Aby to lepiej zrozumieć, od razu pokażę jak to wszystko działa w praktyce.
Załóżmy, że naszym zadaniem jest dostosowanie temperatury w pomieszczeniu (np. tym w którym aktualnie znajduje się czytelnik) do takiej wartości jaka zostanie ustawiona. Proponuję aby czytelnik sporządził listę punktów wg których powinien działać regulator. Moja lista jest następująca:
1) Zapamiętaj ustawioną (żądaną) wartość temperatury
2) Zapamiętaj aktualną temperaturę
3) Jeżeli aktualna temperatura nie przekracza wartości ustawionej z tolerancją 3 stopni C, to przejdź do punktu 1 (temperatura aktualna < temperatura ustawiona + 3 oraz temperatura aktualna > temperatura ustawiona - 3)
4) Jeżeli temperatura aktualna jest większa od temperatury ustawionej, to zmniejsz temperaturę aktualną i przejdż do punktu 1
5) W przeciwnym wypadku (temperatura aktualna mniejsza od temperatury ustawionej) zwiększ temperaturę aktualną i przejdź do punktu 1

Rysunek 2. Schemat blokowy rozwiązania postawionego problemu.
Jeżeli przyjmiemy, że lista działań przedstawiona powyżej jest algorytmem, to rysunek 2 przedstawia graficzną reprezentację tego algorytmu. Aby poprawnie zinterpretować ten rysunek należy zacząć od punktu oznaczonego owalem z napisem START. W tym punkcie zaczyna się algorytm. Linia wychodząca z tego bloku prowadzi do równoległoboku oznaczającego wprowadzenie informacji o temperaturze ustawionej (T_U). Dalej mamy blok (również równoległobok) wprowadzający informację o temperaturze aktualnej (T_A). Po otrzymaniu informacji o temperaturach sprawdzany jest warunek (blok z dwoma wyjściami - 'Tak' i 'Nie' - nazywany blokiem warunkowym). Warunek ten zapisany jest w postaci | T_U - T_A | <= 3. Forma ta pozwala sprawdzić czy temperatura aktualna mieści się dopuszczalnych granicach ( zapis | T_U - T_A | można interpretować jako 'odległość' jednej temperatury od drugiej). Poprzez zapis | x | rozumiemy wartość bezwzględną z 'x' (przypomnę, że wartość bezwzględna z 'x' jest zawsze dodatnia. Jeżeli x jest mniejszy od zera to odrzuca się minus np. dla -2.5 wartość bezwzględna to 2.5). Jeżeli warunek zawarty wewnątrz bloku jest spełniony wtedy obierana jest droga oznaczona napisem "Tak" i sterowanie wraca do bloków wczytujących temperaturę. W przeciwnym wypadku obierana jest droga oznaczona "Nie" co spowoduje przejście do kolejnego bloku warunkowego. W bloku tym podejmowana jest decyzja dotycząca korekty (zwiększenia lub zmniejszenia) aktualnej temperatury. Po podjęciu tej decyzji wykonywana jest operacja korekty a następnie sterowanie wraca do bloków wczytywania temperatur. Proszę zauważyć, że algorytm ten 'jest czuły' na różnicę temperatur przekraczającą 3 stopnie C co w realnym rozwiązaniu byłoby zdecydowanie niedopuszczalne. Przecież 21 stopni C daje zupełnie inny komfort przebywania w pokoju niż 25 stopni. Tutaj jednak chodzi o pokazanie idei działania algorytmu.
Ten schemat blokowy narysowałem w systemowym MS Paint aby pokazać, że do tworzenia takich schematów nie są potrzebne żadne specjalne narzędzia (choć jest ich sporo). Tak naprawdę wystarczy kartka papieru i ołówek. Dla programistów umiejętność tworzenia schematów blokowych jest tak podstawowa, że często o niej zapominają. Dzieje się tak dlatego, że na codzień nie rysuje się schematów reprezentujących najbardziej podstawe problemy. Zamiast tego programiści od razu przystępują do kodowania (czyli przełożenia algorytmu na język komputera). Jednakże każdy programista poproszony o zobrazowanie dowolnego 'kawałka' stworzonego przez siebie kodu przy pomocy schematu blokowego zrobi to za pewne bez większego wysiłku. Warto też dodać, że schemat blokowy zazwyczaj opisuje jedynie ideę działania programu (a częściej pewnej jego części) i bardzo rzadko uwzględnia wszystkie szczegóły związane z implementacją (kodem programu).
Przebrnęliśmy już przez dwa z trzech (częściej czterech) etapów rozwiązania postawionego zadania. Mamy algorytm oraz jego graficzną reprezentację. Teraz pozostaje zakodowanie tego algorytmu przy pomocy jakiegoś języka. Z tym etapem wiąże się nieodłącznie wybór Języka Programowania. Trzeba tutaj dodać, że wybór jest naprawdę ogromny. Chyba nikt nie zna dokładnej liczby dostępnych języków programowania, myślę jednak, że nie będzie grubą przesadą oszacowanie na poziomie kilku/kilkunastu tysięcy. Przyglądając się historii rozwoju języków programowani i ich translatorów (czyli programów, które przekształcają kod programu zapisany w pewnym języku programowania na postać zrozumiałą dla komputera) można zauważyć dążenie do tworzenia takich języków, które skupiają się na opisie modelowanej rzeczywistości a ukrywają szczegóły działania. Z kolei starsze języki przymuszają programistę do myślenia o najmniejszych drobiazgach już na poziomie projektowania programu.
Ja do zakodowania przedstawionego algorytmu wybrałem nieco zapomniany już dziś język o nazwie BASIC. Język ten w swojej "czystej" formie ma bardzo niewiele wspólnego ze współczesnymi jego odmianami (jak np. Visual Basic .NET firmy Microsoft). Po pierwsze jest on bardzo prosty i pozwala na w miarę dokładne odwzorowanie algorytmu. Po drugie wszelkie idee współczesnych języków programowani są mu obce. Jest on za to bardzo łatwo dostępny na wszystkich platformach (MS Windows/ UNIX / LINUX / DOS. Stare komputery miały wbudowany interpreter języka BASIC). Czytelnikowi, który pragnie spróbować swoich sił jako programista języka BASIC a nie ma tego języka zainstalowanego na swoim komputerze polecam przejrzenie Sieci pod tym kątem (polecam np. smallBasic dostępny na stronie http://smallbasic.sourceforge.net/ - istnieją implementacje na wiele platform).
Dysponując językiem programowani pozostaje jedynie zakodować stworzony wcześniej algorytm. W rozwiązywaniu realnego zadania posiadali byśmy zapewne wszystkie niezbędne urządzenia oraz dokumentację opisującą sposób współpracy z nimi. W naszym przypadku sprawa jest jednak dodatkowo skomplikowana ponieważ tak na prawdę nie dysponujemy przecież żadnym urządzeniem, które sprawdzi temperature powietrza. Nie mamy też urządzenia do wczytania temperatury ustawionej. Na szczęście możemy zasymulawać zachowanie tych urządzeń (co niestety wprowadzi częściowe odstępstwo od algorytmu). Kod który znajduje się poniżej jest właśnie implementacją (realizacją) postawionego nam zadania:
TA = 100
TU = 23
Label Start
Print "Wczytanie danych o temperaturach : T_A="+TA+", T_U="+TU
Delay 250
Label PierwszyWarunek
If Abs(TU-TA)<=3 Then Goto Start
Label DrugiWarunek
If TU>TA Then Goto ZwiekszTA Else Goto ZmniejszTA
Label ZwiekszTA
TA=TA+1
Goto Start
Label ZmniejszTA
TA=TA-1
Goto Start
Kilka słów wyjaśnienia. Jest to kod źródłowy programu regulatora temperatury, który możemy uruchomić za pomocą (prawie) dowolnego translatora języka BASIC. Jeżeli czytelnik chce uruchomić ten program przy pomocy smallBasic to wystarczy skopiować treść programu a następnie wkleić go do okienka edytora smallBasic i uruchomić wykonywanie (F9). Zasada działania języka BASIC jest taka, że wykonuje on kolejne następujące linie kodu. W przypadku powyższego programu najpierw przypisujemy wartości dla temperatury aktualnej (linia: TA = 100) oraz temperatury ustawionej (linia: TU = 23). Dzięki temu program uzyskuje pewien stan początkowy. Słowo Label służy w języku Basic (w implementacji smallBasic) do oznaczenia miejsca w programie. Działa to nieco podobnie do zakładki książkowej. Najpierw oznaczamy miejsce poprzez umieszczenie tam słowa Label oraz nazwy. Później, jeżeli zajdzie taka potrzeba, możemy w to miejsce wrócić. Następnie mamy linię zawierającą słowo "Print". Jest to komenda służąca do wydrukowania napisów. To co jest w dalszej części linii ujęte w cudzysłów bedzie wydrukowane dosłownie, natomiast to co znajduje się poza cudzysłowiem zostanie zamienione na wartość. Tak więc zobaczymy napis zawierający w sobie dwie liczby (w miejscach TA i TU pojawią się odpowiednie wartości). Linijkę "Delay 250" możemy zignorować. Następnie widzimy kolejne miejsce oznaczone poprzez "Label" - czyli kolejną zakładkę. Pod nią mamy następującą linijkę:
If Abs(TU-TA)<=3 Then Goto Start
Linijka ta jest zakodowanym (w języku Basic) zapisem punktu nr 3 algorytmu, który brzmi: "Jeżeli aktualna temperatura nie przekracza wartości ustawionej z tolerancją 3 stopni C to przejdż do punktu 1". Słowo "If" należy tłumaczyć jako "jeżeli", słowo Asb - to "wartość bezwzblędna" (zobacz opis schematu blokowego), symbol "<=" czytamy jako "mniejsze lub równe". Słowo "Then" oznacza "w takim wypadku" a "Goto Start" - przejdź do miejsca oznaczonego nazwą "Start". A więc całość możemy przeczytać jako: Jeżeli wartość bezwzględna z (TU-TA) jest mniejsza lub równa 3 w takim wypadku przejdź do miejsca oznaczonego "Start". Miejsce to już poznaliśmy przy okazji omawiania słowa Label. To właśnie tam przejdzie sterowanie programu w przypadku spełnienia warunku.
Pozostała część programu zbudowana jest ze składowych omówionych właśnie przed chwilą (pojawiają się w niej : Label, If - Then, Goto). Wyjątkiem jest słowo Else - oznaczające "w przeciwnym wypadku". Z taką wiedzą czytelnik potrafi już samodzielnie przeczytać resztę programu do czego serdecznie zachęcam. Proponuję również poeksperymentowanie z tym programem w celu nabycia nowej wiedzy.
Na zakończenie jeszcze jedna sprawa. W schemacie blokowym jest błąd logiczny. Odnalezienie tego błędu proponuję potraktować jako test logicznego myślenia, który jak napisałem na początku jest przecież przepustką do świata programistów.
Tomasz Siwarga
tomsiw@wp.pl
|